'use strict'

let net = require('net')
let EventEmitter = require('events').EventEmitter

const MSG_HEADER_SIZE = 22 //数据头的长度
const RPC_DATA_MAX_LENGTH = 2147483647 //数据包最大的长度

//服务端类
class TcpServer {
	constructor(name) {
		this.netServer = null
		this.name = name
		this.curId = 1
	}

	//启动服务器
	createServer(port, cb) {
		let self = this
		this.netServer = net.createServer(function(socket) {
			let _socket = new Socket(++this.curId, socket)
			cb(_socket)
		})
		this.netServer.listen(port)
		console.log(self.name + ' 服务器 listen on 127.0.0.1:' + port)
	}
}

exports.TcpServer = TcpServer

//socket服务类
class Socket extends EventEmitter {
	constructor(sid, socket) {
		EventEmitter.call(this)
		let self = this
		this.id = sid
		this.reqId = 0 //序列号
		this.socket = socket
		this.inData = [] //缓存接收的数据
		this.dataLen = 0 //缓存接收的数据的长度
		this.msgSize = 0 //数据包的长度（在包头中占4字节）
		this.serialNum = 0 //数据包的序列号（在包头中占2字节）
		this.msgType = 0 //消息体的类型（在包头中占2字节）

		socket.on('data', function(data) {
			self.inData.push(data)
			self.dataLen += data.length
			self._handleInData() //处理分包，粘包数据
		})

		socket.on('close', function(data) {
			//console.log('close')
			//self.emit('close', data)
		})

		socket.on('error', function(data) {
			//console.log('error')
			//self.emit('error', data)
		})
	}

	//发送数据
	send(data, reqId, msgId) {
		if (data.length >= RPC_DATA_MAX_LENGTH) {
			console.log('发送的数据包数据太长，必须小于' + RPC_DATA_MAX_LENGTH)
			return
		}

		if (msgName.length > 18) {
			console.log('消息名字数据太长，必须小于' + 19)
			return
		}
		var len = Buffer.byteLength(data)
		var dataBuf = new Buffer(MSG_HEADER_SIZE + len)
		dataBuf.writeUInt16BE(0, 0) //协议头0
		dataBuf.writeUInt16BE(0, 2) //协议头1
		dataBuf.writeUInt16BE(0, 4) //协议头2
		dataBuf.writeUInt16BE(0, 6) //协议头3
		dataBuf.writeUInt16BE(0, 8) //协议头版本号
		dataBuf.writeUInt32BE(0, 10) //服务版本号
		dataBuf.writeUInt32BE(len + 4, 14) //数据包长度
		dataBuf.writeUInt32BE(msgId, 18) //数据包id
		dataBuf.write(data, 22)
		this.socket.write(dataBuf)
	}

	//处理分包，粘包数据
	_handleInData() {
		let self = this
		if (this.msgSize === 0) {
			if (this.dataLen < MSG_HEADER_SIZE) {
				//数据长度小于数据头定义的长度，返回继续接受数据
				return
			}
			let header = this._readLenData(MSG_HEADER_SIZE) //获取数据头
			this.msgSize = header.readInt32BE(10) //数据包的长度
			this.serialNum = header.readInt16BE(18) //数据包的序列号
			this.msgName = header.toString('utf8', 8, 8 + msgNameLen) //消息体的类型名字
		}

		if (this.dataLen < this.msgSize) {
			//数据长度小于数据包的长度，返回继续接受数据
			return
		}

		let msgBody = this._readLenData(this.msgSize) //读取数据包的数据
		this.msgSize = 0
		this.emit('data', msgBody.toString(), this.serialNum, this.msgName)

		if (this.inData.length > 0) {
			//缓存数据不为空，继续处理数据
			setImmediate(function() {
				self._handleInData()
			})
		}
	}

	// 读取数据，同时移除读取的数据
	_readLenData(len) {
		let bufArray = this.inData
		let retBuffer = new Buffer(len)
		let offset = 0
		while (bufArray.length > 0) {
			var buf = bufArray[0]
			if (buf.length == len) {
				//buf的数据等于要读取的数据len
				buf.copy(retBuffer, offset, 0, len)
				this.dataLen -= len
				bufArray.shift()
				return retBuffer
			} else if (buf.length > len) {
				//buf的数据大于要读取的数据len
				buf.copy(retBuffer, offset, 0, len)
					// slice source data
				bufArray[0] = buf.slice(len)
				this.dataLen -= len
				return retBuffer
			} else {
				buf.copy(retBuffer, offset, 0, buf.length)
				offset += buf.length
				this.dataLen -= buf.length
				len -= buf.length
				bufArray.shift()
			}
		}
		return retBuffer
	}
}
